home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDX350 / STEPART.BAK < prev    next >
Encoding:
Text File  |  2001-02-09  |  45.6 KB  |  1,795 lines

  1. /*
  2.  * Partition editing and picking.
  3.  *
  4.  * 09-Dec-87    ml.    Added pheader() to take care of placing partition
  5.  *            headers at good sectors.
  6.  * 14-Jan-88    ml.    Added chkpart() to make sure partition scheme does
  7.  *            not map pass end of device.
  8.  * 02-Dec-88     jye. Change and add codes so that can be used for MS-DOS
  9.  *
  10.  * 12-Dec-89    jye. Fixed a bug in stuffamt() so that correctly show three
  11.  *                digits or more in the partitioning deialog box.
  12.  */
  13.  
  14. #include "obdefs.h"
  15. #include "gemdefs.h"
  16. #include "osbind.h"
  17. #include "mydefs.h"
  18. #include "part.h"
  19. #include "bsl.h"
  20. #include "hdx.h"
  21. #include "addr.h"
  22. #include "error.h"
  23. #include "ipart.h"
  24.  
  25. #define ROLL1 1            /* move the bar one step */
  26. #define ROLL4 4            /* move the bar four steps */
  27. #define NULL 0L            /* the nill pointer */
  28.  
  29. extern int wdesk;
  30. extern int hdesk;
  31. extern long gbslsiz();
  32. extern long getdsiz();
  33. extern long bslsiz;
  34. extern SECTOR badbuf[];        /* bad sectors buffer */
  35. extern long ostack;
  36. extern long sptrk;                /* sector per track */
  37. extern long disksiz;            /* size of disk in blocks */
  38. extern int yesscan;            /* the flag for the func. IBMGPART use */
  39. extern int npart;            /* number of partitions */
  40. extern int ext;            /* the index that point to the extended partition */
  41. extern int extend;        /* the index that point to the end of extended */
  42. extern char ttscsi;        /* 1: SCSI bus drive */
  43.  
  44.  
  45. /*
  46.  * Global variables these routines communicate with
  47.  *
  48.  */
  49. static PART *pinfo;        /* -> partition block */
  50. static int totcyl;        /* total # of cylinder */
  51. static long sizleft;    /* size of unused disk in blocks */
  52. static long extleft;    /* size of unused extended partition in blocks */
  53. static int formw, formh;
  54. static int lx, ly, sx, sy;
  55. static int ok2draw;        /* 0: don't draw PARTPNL boxes */
  56. static char partnames[NAMSIZ];    /* partition name buffer */
  57. static int menuflg;        /* negative: never called partmenu */
  58. static int pnlflg;        /* 1: partition scheme comes from panel */
  59. static int along;        /* 1: will not redraw and clean the box */
  60. static int first;        /* flag for add bad and good sectors only one time */
  61. long sumsiz;            /* the sum of bytes of root sectors */
  62. int tolpart;            /* the total of number partitions */
  63. int epty;                /* the y-coordinate of the moving bar */
  64. int uplim;                /* index of dialog box */
  65. int lowlim;                /* index of dialog box */
  66. int restept;            /* 1: rest the moving bar to initial place */
  67. DPART *headptr;            /* the head pointer of structure */
  68. long ratio, bps;
  69. long nill = (long)NULL;
  70. int prevnpart;            /* former number of partitions */
  71.  
  72.  
  73. /*
  74.  * Figure out partition information;
  75.  *    return OK if xpinfo[] is filled-in,
  76.  *         ERROR on [CANCEL] or something.
  77.  */
  78. sfigpart(bs, dev, rpinfo)
  79.  
  80. char *bs;
  81. int dev;
  82. PART **rpinfo;
  83.  
  84. {
  85.     int ret;
  86.  
  87.     lowlim = 0;
  88.     uplim = 4;
  89.     first = 0;
  90.     along = 0;        /* will redraw and clean the box */
  91.     restept = 0;
  92.  
  93.     /*  Get partition information from disk's root block. */
  94.     if ((ret = getroot(dev, bs, (SECTOR)0)) != 0) {
  95.         if (tsterr(ret) != OK)
  96.             err(rootread);
  97.         return ERROR;
  98.     }
  99.     yesscan = 0;
  100.     
  101.     /* get bad sectors list size */
  102.     if ((bslsiz = gbslsiz(dev)) == 0L) {    /* no bsl */
  103.         return err(oldfmt);
  104.     } else if (bslsiz < 0L) {            /* error occurred */
  105.         if (bslsiz == ERROR)            /* read error */
  106.             err(rootread);
  107.         return ERROR;                /* medium changed error */
  108.     }
  109.  
  110.       if ((ret = chkroot(dev, bs)) == -3)    { /*don't have to show the alert box */ 
  111.         return ERROR;
  112.     } else if (ret != OK)    {
  113.            return err(cruptfmt);
  114.     }
  115.  
  116.     disksiz = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  117.     if (stgpart(dev, bs, (PART *)&pinfo) == ERROR)    {
  118.         if (pinfo > 0) Mfree(pinfo);
  119.         return ERROR;
  120.     }
  121.     if (ext != NO_EXT)    sortpart(pinfo, USER_ED);
  122.  
  123.     /* put partition infomations into the dynamic structure */
  124.     if (part2dpart(npart) == ERROR)        {
  125.         return ERROR;
  126.     }
  127.     menuflg = -1;    /* first time through */
  128.     restept = 1;
  129.     prevnpart = npart;
  130.     for (;;)
  131.     {
  132.     switch (sdoscrbar())
  133.     {
  134.         case SPMENU:            /* chose from menu */
  135.             switch (spartmenu())
  136.             {
  137.                 case PPOK:        *rpinfo = pinfo;
  138.                                 return OK;    /* [OK] */
  139.                 default:
  140.                 case PPCN:        if (pinfo > 0) Mfree(pinfo);
  141.                                 if (headptr > 0) free(headptr);
  142.                                 return BAILOUT;    /* [CANCEL] */
  143.                 case PPEDIT:    restept = 1; 
  144.                                 lowlim = 0;
  145.                                 uplim = 4;
  146.                                 break;        /* continue and edit */
  147.             }
  148.             break;
  149.  
  150.         case EXPERT:    along = 0;
  151.                         lowlim = 0;
  152.                         uplim = 4;
  153.                         restept = 1;
  154.                         ext = 1;        /* set default to 1 */
  155.                         extend = npart-2;
  156.                         switch (doexpert())    {
  157.                             case NOSEL:        if (pinfo > 0)    {
  158.                                                 inipart(pinfo, prevnpart);
  159.                                                 Mfree(pinfo);
  160.                                             }
  161.                                             if (headptr > 0) free(headptr);
  162.                                             return BAILOUT;    /* [CANCEL] */
  163.                             case SELOK:    pnlflg = 1;    
  164.                                         if (pinfo > 0)    {
  165.                                             inipart(pinfo, prevnpart);
  166.                                             Mfree(pinfo);
  167.                                         }
  168.                                         if (dpart2part(ext) == ERROR) {
  169.                                             if (headptr > 0) free(headptr);
  170.                                             if (pinfo > 0) Mfree(pinfo);
  171.                                                 return ERROR;
  172.                                         }
  173.                                         *rpinfo = pinfo;
  174.                                         return OK;
  175.                             default:
  176.                             case TOEDIT: break;
  177.                         }
  178.  
  179.         case SCRUP:      break;
  180.         case SCRDN:      break;
  181.         case SCRBAR:      break;
  182.         case SCREPT:      break;
  183.         case SUNDO:      break;
  184.  
  185.         default:
  186.         case SEPOK:    *rpinfo = pinfo;
  187.                     return OK;
  188.         case SEPCN: if (pinfo > 0) Mfree(pinfo);
  189.                     if (headptr > 0) free(headptr);
  190.                     return BAILOUT;
  191.     }
  192.     }
  193. }
  194.  
  195. int objnums[] = { SPARTNM0, SPARTNM1, SPARTNM2, SPARTNM3};
  196. int objups[] = {SEP0UP, SEP1UP, SEP2UP, SEP3UP};
  197. int objdns[] = {SEP0DN, SEP1DN, SEP2DN, SEP3DN};
  198. int objsizs[] = {SEP0SIZ, SEP1SIZ, SEP2SIZ, SEP3SIZ};
  199. char *sizstr[6] = {"1000.0Mb0", "1000.0Mb0", "1000.0Mb0", "1000.0Mb0", 
  200.                    "1000.0Mb0", " 999 partition(s)"};
  201. char *numstr[4] = {"#999", "#999", "#999", "#999"};
  202.  
  203.  
  204. int objnum[] = { PART1, PART2, PART3, PART4, PARTX, PARTY, PARTZ};
  205. char *xsizstr[7] = {"1000.0Mb0", "1000.0Mb0", "1000.0Mb0", "1000.0Mb0", 
  206.                    "1000.0Mb0", "1000.0Mb0", "1000.0Mb0"};
  207. int objsiz[] = {PART1MB, PART2MB, PART3MB, PART4MB, PARTXMB, PARTYMB, PARTZMB};
  208. char *xnumstr[7] = {"#999", "#999", "#999", "#999", "#999", "#999", "#999"};
  209. int objsel[] = { SELECT1, SELECT2, SELECT3, SELECT4, SELECT5, SELECT6};
  210. char *selstr[6] = {"from #2 to #99", "from #2 to #99", "from #2 to #99", 
  211.                     "from #3 to #99", "from #3 to #99", "from #4 to #99" };
  212. doexpert()
  213. {
  214.  
  215.     int i, lastpno, pno;
  216.     int run = 1;
  217.     int erase = 0;
  218.     int but;
  219.  
  220.     ok2draw = 0;
  221.  
  222.  
  223.     exppnl[TOEDIT].ob_state = NORMAL;
  224.     exppnl[NOSEL].ob_state = NORMAL;
  225.     exppnl[SELOK].ob_state = NORMAL;
  226.  
  227.     drawsel(2, npart-2, 0, exppnl);
  228.     drawsel(2, npart-1, 1, exppnl);
  229.     drawsel(2, npart, 2, exppnl);
  230.     drawsel(3, npart-1, 3, exppnl);
  231.     drawsel(3, npart, 4, exppnl);
  232.     drawsel(4, npart, 5, exppnl);
  233.  
  234.  
  235.     for (i = 0; i < 7; i++)        {
  236.         if (npart > 7)    {
  237.             if (i > 3)    {
  238.                 if (i == 4)
  239.                     lastpno = npart - i + 1;
  240.                 drawpart(i, lastpno++, exppnl);
  241.             } else {
  242.                 drawpart(i, i, exppnl);
  243.             }
  244.         } else if (npart == 5)    {
  245.             if (i > 4)    {
  246.                 pno = -1;
  247.                 drawpart(i, pno, exppnl);
  248.             } else {
  249.                 drawpart(i, i, exppnl);
  250.             }
  251.         } else if (npart == 6)    {
  252.             if (i > 5)    {
  253.                 pno = -1;
  254.                 drawpart(i, pno, exppnl);
  255.             } else {
  256.                 drawpart(i, i, exppnl);
  257.             }
  258.         } else {
  259.             drawpart(i, i, exppnl);
  260.         }
  261.     }
  262.  
  263.     /* set the default selected */
  264.     exppnl[SELECT1].ob_state = NORMAL | SELECTED;
  265.     exppnl[SELECT2].ob_state = NORMAL;
  266.     exppnl[SELECT3].ob_state = NORMAL;
  267.     exppnl[SELECT4].ob_state = NORMAL;
  268.     exppnl[SELECT5].ob_state = NORMAL;
  269.     exppnl[SELECT6].ob_state = NORMAL;
  270.     turnexton(1, npart-2);
  271.  
  272.     ARROW_MOUSE;
  273.     dsplymsg(exppnl);
  274.  
  275.     ++ok2draw;
  276.     while (run)        {
  277.         switch((but = form_do(exppnl, -1)))        {
  278.             case TOEDIT:    run = 0; 
  279.                             break;
  280.             case NOSEL:        run = 0;
  281.                             erase = 1;
  282.                             break;
  283.             case SELOK:        run = 0;
  284.                             erase = 1;
  285.                             break;
  286.             case SELECT1:    ext = 1;
  287.                             extend = npart - 2;
  288.                             turnexton(1, npart-2);
  289.                             break;
  290.             case SELECT2:    ext = 1;
  291.                             extend = npart - 1;
  292.                             turnexton(1, npart-1);
  293.                             break;
  294.             case SELECT3:    ext = 1;
  295.                             extend = npart;
  296.                             turnexton(1, npart);
  297.                             break;
  298.             case SELECT4:    ext = 2;
  299.                             extend = npart - 1;
  300.                             turnexton(2, npart-1);
  301.                             break;
  302.             case SELECT5:    ext = 2;
  303.                             extend = npart;
  304.                             turnexton(2, npart);
  305.                             break;
  306.             case SELECT6:    ext = 3;
  307.                             extend = npart;
  308.                             turnexton(3, npart);
  309.                             break;
  310.         }
  311.     }
  312.     if (erase)    {
  313.         erasemsg();
  314.         BEE_MOUSE;
  315.     }
  316.     return but;
  317. }
  318.  
  319. turnexton(stnum, endnum)
  320. int stnum;        /* the number that start to turn on the extended partition */
  321. int endnum;        /* the number that end to turn on the extended partition */
  322. {
  323.     int i;
  324.  
  325.     if (npart > 7)    {
  326.         endnum = 7 - (npart - endnum);
  327.     }
  328.     for (i = 0; i < 7; i++)    {
  329.         exppnl[objsiz[i]].ob_state = NORMAL;
  330.         if ((i >= stnum) && (i < endnum))    {
  331.             exppnl[objsiz[i]].ob_state |= SELECTED;
  332.         }
  333.         if (ok2draw)    {
  334.             objc_draw(exppnl, objsiz[i], MAX_DEPTH, 0, 0, wdesk, hdesk);
  335.         }
  336.  
  337.     }
  338.     ok2draw++;
  339. }
  340.  
  341.  
  342.  
  343.  
  344. drawsel(stnum, tonum, num, pnl)
  345. int stnum;        /* the first extended partition number */
  346. int tonum;        /* the last extended partition number */
  347. int num;        /* the number of selected extended partition scheme */
  348. OBJECT *pnl;
  349. {
  350.  
  351.     /* set the select range in the dialog box */
  352.     calextnum(stnum, tonum, selstr[num]);
  353.     (pnl[objsel[num]].ob_spec)->te_ptext = selstr[num];
  354.     if (ok2draw)    {
  355.         objc_draw(pnl, objsel[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  356.     }
  357. }
  358.  
  359.  
  360. drawpart(num, pno, pnl)
  361. int num;        /* the number of selected extended partition scheme */
  362. int pno;        /* the partition number */
  363. OBJECT *pnl;
  364. {
  365.     DPART *pinfo, *addr();
  366.  
  367.     if (pno == NO_EXT)    { /* not exists */
  368.         pnl[objsiz[num]].ob_spec = "Unused";
  369.         pnl[objsiz[num]].ob_state = NORMAL;
  370.         pnl[objsiz[num]].ob_flags = TOUCHEXIT;
  371.         (pnl[objnum[num]].ob_spec)->te_ptext = "     ";
  372.     } else {
  373.         pinfo = addr(pno);
  374.         stuffamt(pinfo->siz, xsizstr[num], 0);
  375.         pnl[objsiz[num]].ob_spec = xsizstr[num];
  376.         pnl[objsiz[num]].ob_state = NORMAL;
  377.         pnl[objsiz[num]].ob_flags = TOUCHEXIT;
  378.  
  379.         stpartnum(pno+1, xnumstr[num]);
  380.         (pnl[objnum[num]].ob_spec)->te_ptext = xnumstr[num];
  381.     }
  382.     if (ok2draw)    {
  383.         objc_draw(pnl, objsiz[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  384.         objc_draw(pnl, objnum[num], MAX_DEPTH, 0, 0, wdesk, hdesk);
  385.     }
  386.  
  387. }
  388.  
  389. sdoscrbar()
  390.  
  391. {
  392.  
  393.     int i, j, but, step;
  394.     int xrun = 1;
  395.     long usesiz;
  396.     DPART *temptr, *addr();
  397.  
  398.     ok2draw = (along) ? 1 : 0;
  399.  
  400.     /* set form for first display */
  401.     scrpnl[SEPOK].ob_state = NORMAL;
  402.     scrpnl[SEPCN].ob_state = NORMAL;
  403.     scrpnl[SPMENU].ob_state = NORMAL;
  404.     scrpnl[SUNDO].ob_state = NORMAL;
  405.  
  406.     if (!first++)    {    /* initially ST partition */
  407.         temptr = headptr;
  408.         for (i = 0; i < npart; i++)    {
  409.             if ((temptr->flg & P_EXISTS) && 
  410.                 (!((temptr->next)->flg & P_EXISTS)))    {
  411.                 temptr->siz += bslsiz + 1; /* add sacrificed space back */
  412.             }
  413.             temptr = temptr->next;
  414.         }
  415.     }
  416.  
  417.     for (i = -1; i < 4; ++i)
  418.          sepadj(0L, i, scrpnl);
  419.     if (restept)    {
  420.         scrpnl[SCREPT].ob_y = 0;
  421.         restept = 0;
  422.     }
  423.     if (!along)        {
  424.         ARROW_MOUSE;
  425.         dsplymsg(scrpnl);
  426.     }
  427.  
  428.     /*
  429.      * Edit the thing;
  430.      * canonical event-driven switch().
  431.      */
  432.     ++ok2draw;
  433.     while (xrun)     {
  434.     along = 0;
  435.     if (npart > 4)    {
  436.         scrpnl[EXPERT].ob_state = NORMAL;
  437.         scrpnl[EXPERT].ob_flags = TOUCHEXIT;
  438.     } else {
  439.         scrpnl[EXPERT].ob_state = DISABLED;
  440.         scrpnl[EXPERT].ob_flags = NONE;
  441.     }
  442.     objc_draw(scrpnl, EXPERT, MAX_DEPTH, 0, 0, wdesk, hdesk);
  443.  
  444.     switch ((but = form_do(scrpnl, -1)))
  445.     {
  446.     case SEPOK:    pnlflg = 1;
  447.                 if (pinfo > 0L)    {
  448.                     inipart(pinfo,prevnpart);
  449.                     Mfree(pinfo);
  450.                 }
  451.                 ext = 1;        /* set the default extended partition */
  452.                 extend = npart - 2;
  453.                 if (dpart2part(ext) == ERROR) return ERROR;
  454.                 xrun = 0;
  455.                 break;
  456.     case SEPCN:    xrun = 0;            /* return */
  457.                     break;
  458.     case EXPERT: if (npart > 4)        {
  459.                     xrun = 0;
  460.                     break;
  461.                  } else {
  462.                      xrun = 1;
  463.                     break;
  464.                  }
  465.     case SCRBAR: if (sdoscrupdn(ROLL4) == ERROR) return ERROR;
  466.                     xrun = 0;
  467.                     break;
  468.     case SCRUP:  if (sdoscrupdn(ROLL1) == ERROR) return ERROR;
  469.                 xrun = 0;
  470.                 break;
  471.     case SCRDN:  if (sdoscrupdn(ROLL1) == ERROR) return ERROR;
  472.                 xrun = 0;
  473.                 break;
  474.     case SCREPT: if (sdoslidebox(scrpnl) == ERROR) return ERROR;
  475.                 xrun = 0;
  476.                 break;
  477.     case SPMENU:    xrun = 0;
  478.                     break;
  479.  
  480.     case SUNDO:     /* restore the starting parameters */
  481.                 lowlim = 0;
  482.                 uplim = 4;
  483.                 if (part2dpart(prevnpart) == ERROR)    return ERROR;
  484.                 for (i = -1; i < NPARTS; ++i)
  485.                     sepadj(0L, i, scrpnl);
  486.                 npart = prevnpart;
  487.                 scrpnl[SCREPT].ob_y = 0;
  488.                 objc_draw(scrpnl, SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  489.                 break;
  490.  
  491.     case SEP0SIZ:xrun = septoggle(0, scrpnl);    break;
  492.     case SEP0UP:    sepadj(MEGABYTE, 0, scrpnl);    break;
  493.     case SEP0DN:    sepadj(-MEGABYTE, 0, scrpnl);    break;
  494.  
  495.     case SEP1SIZ:xrun = septoggle(1, scrpnl);    break;
  496.     case SEP1UP:    sepadj(MEGABYTE, 1, scrpnl);    break;
  497.     case SEP1DN:    sepadj(-MEGABYTE, 1, scrpnl);    break;
  498.  
  499.     case SEP2SIZ:xrun = septoggle(2, scrpnl);    break;
  500.     case SEP2UP:    sepadj(MEGABYTE, 2, scrpnl);    break;
  501.     case SEP2DN:    sepadj(-MEGABYTE, 2, scrpnl);    break;
  502.  
  503.     case SEP3SIZ:xrun = septoggle(3, scrpnl);    break;
  504.     case SEP3UP:    sepadj(MEGABYTE, 3, scrpnl);    break;
  505.     case SEP3DN:    sepadj(-MEGABYTE, 3, scrpnl);    break;
  506.       }
  507.   }
  508.  
  509.  
  510.     /*
  511.      * Draw shrinking box and cleanup the screen;
  512.      * return thing that caused our exit.
  513.      */
  514.     if (!along)    {
  515.         erasemsg();
  516.         BEE_MOUSE;
  517.     }
  518.     return but;
  519. }
  520.  
  521.  
  522.  
  523.  
  524. /* 
  525.  * conver the partition number for the dialog box to the string .
  526.  *
  527.  */
  528.  
  529. calextnum(stnum, tonum, str)
  530.  
  531. int stnum,tonum;
  532. char *str;
  533.  
  534. {
  535.     int  i = 0;
  536.     int addspace = 0;
  537.     char tem[10];
  538.  
  539.     /* set the partition number header */
  540.     *str++ = 'f';
  541.     *str++ = 'r';
  542.     *str++ = 'o';
  543.     *str++ = 'm';
  544.     *str++ = ' ';
  545.     *str++ = '#';
  546.     *str++ = stnum % 10 + '0';
  547.     *str++ = ' ';
  548.     *str++ = 't';
  549.     *str++ = 'o';
  550.     *str++ = ' ';
  551.     *str++ = '#';
  552.     /* conver the integer to ASCII */
  553.     do    {    /* generate digits in reverse order */
  554.         tem[i++] = tonum % 10 + '0';    /* get next digits */
  555.     } while ((tonum /= 10) > 0);        /* delete it */
  556.  
  557.     if (i == 1)    {
  558.         addspace = 1;
  559.     }
  560.     for (; i > 0; )    { /* reverse string 'str' in place */
  561.         *str++ = tem[--i];
  562.     }
  563.     if (addspace)    *str++ = ' ';
  564.        *str = '\0';
  565. }
  566.  
  567.  
  568. sdoscrupdn(roll)
  569. int roll;
  570.  
  571. {
  572.      int gr_mkmx, gr_mkmy;
  573.     int gr_mkmstate, gr_mkkstate;
  574.     int barht, barx, bary;
  575.     int eptx, eptht;
  576.  
  577.     along = 1;
  578.     barht = scrpnl[SCRBAR].ob_height;
  579.     eptht = scrpnl[SCREPT].ob_height;
  580.     graf_mkstate(&gr_mkmx, &gr_mkmy, &gr_mkmstate, &gr_mkkstate);
  581.     objc_offset(scrpnl, SCREPT, &eptx, &epty);
  582.     objc_offset(scrpnl, SCRBAR, &barx, &bary);
  583.     /* check which part of bar was clicked */
  584.     if (gr_mkmy > (epty+eptht))    {    /* low part of bar was clicked */
  585.         if (roll == ROLL4)    {
  586.             if ((eptht > (bary+barht-epty-eptht)) || (lowlim == 20))    {
  587.                 scrpnl[SCREPT].ob_y = barht - eptht;
  588.             } else {
  589.                 scrpnl[SCREPT].ob_y += eptht;
  590.             }
  591.             lowlim = ((24-lowlim) < 4) ? (24) : (lowlim+4); 
  592.             if ((lowlim + 4) > uplim) uplim += 4;
  593.             if (uplim > npart)    {
  594.                 if (creatmem(ROLL4) == ERROR)    {
  595.                     return ERROR;
  596.                 }
  597.             }
  598.         } else if (lowlim == 24)    { /* the empty bar is on the bottom */
  599.             return OK;
  600.         } else {
  601.             if ((eptht > ((bary+barht-epty-eptht) * 4)) || (lowlim == 23))    {
  602.                 scrpnl[SCREPT].ob_y = barht - eptht;
  603.             } else {
  604.                 scrpnl[SCREPT].ob_y += eptht / 4;
  605.             }
  606.             lowlim++;
  607.             if ((lowlim + 4) > uplim)      uplim++;
  608.             if (uplim > npart)    {
  609.                 if (creatmem(ROLL4) == ERROR)    {
  610.                     return ERROR;
  611.                 }
  612.             }
  613.         }
  614.     } else if (gr_mkmy < epty)    {    /* upper part of bar was clicked */
  615.         if (roll == ROLL4)    {
  616.             if ((eptht > (epty - bary)) || (lowlim <= 4))    {
  617.                 scrpnl[SCREPT].ob_y = 0;
  618.                 lowlim = 0;
  619.             } else {
  620.                 scrpnl[SCREPT].ob_y -= eptht;
  621.                 lowlim -= 4;
  622.             }
  623.         } else {
  624.             if ((eptht > ((epty - bary) * 4)) || (lowlim == 1))    {
  625.                 scrpnl[SCREPT].ob_y = 0;
  626.             } else {
  627.                 scrpnl[SCREPT].ob_y -= eptht / 4;
  628.             }
  629.             if (lowlim)     {
  630.                 lowlim--;
  631.             }
  632.         }
  633.     }
  634.     objc_draw(scrpnl,SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  635. }
  636.  
  637.  
  638. #define WHITEBAR 24        /* when the white bar on the bottom, the */
  639.                         /* 'lowlim' will equal to 24 */
  640. sdoslidebox(tree)
  641.  
  642. OBJECT *tree;
  643.  
  644. {
  645.     int gr_wreturn, eptatmax;
  646.     int numofmem;            /*   # of memories to be allocated */
  647.  
  648.     along = 1;
  649.     eptatmax = tree[SCRBAR].ob_height - tree[SCREPT].ob_height;
  650.     gr_wreturn = graf_slidebox(tree, SCRBAR, SCREPT, 1);
  651.     lowlim = (WHITEBAR * gr_wreturn) / 1000;
  652.     if ((lowlim >= uplim) || ((lowlim + 4) > uplim))     {
  653.         uplim = lowlim + 4;
  654.         if (uplim > npart)    {
  655.             numofmem = uplim - npart;
  656.             if (creatmem(numofmem) == ERROR)    {
  657.                 return ERROR;
  658.             }
  659.         }
  660.     }
  661.     /*
  662.     tree[SCREPT].ob_y = (eptatmax * gr_wreturn) / 1000;
  663.     */
  664.     tree[SCREPT].ob_y = (eptatmax * lowlim ) / 24;
  665.     objc_draw(tree, SCRBAR, MAX_DEPTH, 0, 0, wdesk, hdesk);
  666. }
  667.  
  668.  
  669.  
  670. /*
  671.  * Toggle partition in/out of existence.
  672.  */
  673. septoggle(n, pnl)
  674. int n;
  675. OBJECT *pnl;
  676. {
  677.     int i; 
  678.     DPART *pinfo, *ppinfo, *npinfo, *addr();
  679.     /*
  680.      * Toggle existance flag,
  681.      * enforce minimum partition size.
  682.      */
  683.     i = n + lowlim;
  684.     pinfo = addr(i);    /* return the structure pointer */
  685.     ppinfo = addr(i-1);    /* return the previous structure pointer */
  686.     npinfo = addr(i+1);    /* return the next structure pointer */
  687.     if ((!(pinfo->flg & P_EXISTS)) && (pinfo->siz) && (ppinfo)
  688.                             && (ppinfo->flg & P_EXISTS)){
  689.         if (maxmsg(pnl,i,tolpart) == NOMAX) return ON;
  690.         pinfo->flg = P_EXISTS;
  691.         sepadj(0L, n, pnl);
  692.     } else if (((pinfo->flg ^= P_EXISTS) & P_EXISTS) 
  693.           && !pinfo->siz) {
  694.         /* make extended partition continue */
  695.         if (!i || ((ppinfo) && (ppinfo->flg & P_EXISTS)))        {
  696.             if (maxmsg(pnl,i,tolpart) == NOMAX) return ON;
  697.             sepadj(MEGABYTE, n, pnl);
  698.         } else {
  699.             sepadj(0L, n, pnl);
  700.         }
  701.     } else if ((!lowlim) && (!i)&&(!(npinfo->flg & P_EXISTS)))    {
  702.         sepadj(0L, n, pnl);
  703.     } else if ((!lowlim) && (!i)&&(pinfo->flg & P_EXISTS))    {
  704.         sepadj(0L, n, pnl);
  705.     } else {             /* do nothing, turn it back to the initial state */
  706.         pinfo->flg ^= P_EXISTS;
  707.         if ((pinfo->flg & P_EXISTS) && (!(npinfo->flg & P_EXISTS))) {
  708.               pinfo->flg ^= P_EXISTS;
  709.             sepadj(0L, n, pnl);
  710.         }
  711.     }
  712.     sepadj(0L, -1, pnl);            /* update #left field */
  713.     return YES;
  714. }
  715.     
  716.  
  717. /*
  718.  * Adjust partition `pno' size by `amt';
  719.  * if `pno' is -1, just recompute and update disk space left indicator.
  720.  *
  721.  * A partition of size zero is disabled.
  722.  */
  723.  
  724. #define HALFMEGA 1024L
  725.  
  726. sepadj(amt, pno, pnl)
  727. long amt;
  728. int pno;
  729. OBJECT *pnl;
  730. {
  731.     int i;
  732.     long siz;
  733.     long sizhas;     /* disk size left in sectors */
  734.     long totsiz = 0;
  735.     DPART *pinfo, *npinfo, *addr();
  736.  
  737.     if (pno < 0) 
  738.         goto fixleft;
  739.     pno += lowlim;
  740.  
  741.     pinfo = headptr;
  742.     /* compute total used */
  743.     while (pinfo->flg & P_EXISTS)    {
  744.             totsiz += pinfo->siz;
  745.             pinfo = pinfo->next;
  746.     }
  747.     pinfo = addr(pno);
  748.     npinfo = addr(pno+1);
  749.     sizhas = disksiz;
  750.  
  751.     /*
  752.      * If total partition size exceeds the disk's
  753.      * capacity, reduce `amt' accordingly.
  754.      */
  755.     if (amt >= 0 && totsiz + amt > sizhas)
  756.     amt = sizhas - totsiz;
  757.  
  758.     if (amt > 0) {
  759.     /*
  760.      * Enforce maximum partition size.
  761.      */
  762.     siz = sizhas - totsiz;            /* siz = #free */
  763.     if (amt > siz) amt = siz;        /* ensure amt <= siz */
  764.     if (pinfo->siz + amt > sizhas)    /* ensure partition not */
  765.         amt = sizhas - pinfo->siz;    /* too big */
  766.  
  767.     /* check the partition size that can't over 256Mb (8K bytes per sect) */
  768.     /* for the reason of hardware                                           */
  769.     if ((pinfo->siz + amt) > 256 * 2048)    {
  770.         form_alert(1, maxpsize);
  771.         return OK;
  772.     }
  773.     pinfo->siz += amt;        /* bump partition size */
  774.     pinfo->flg = P_EXISTS;
  775.     } else if (amt < 0) {
  776.     amt = -amt;
  777.     if (pinfo->siz > amt) {        /* reduce partition size */
  778.         pinfo->siz -= amt;
  779.         if ((pinfo->siz < HALFMEGA) && (npinfo->flg & P_EXISTS))
  780.             pinfo->siz = amt;
  781.     } else if ((pinfo->siz <= amt) &&
  782.                 (!(npinfo->flg & P_EXISTS)))    {
  783.         /* reduce partition size */
  784.         pinfo->siz = 0L;
  785.     } 
  786.   }
  787.  
  788.     /*
  789.      * Enforce minimum partition size of half mega byte 
  790.      */
  791.     if (pinfo->siz < HALFMEGA)
  792.     pinfo->siz = 0L;
  793.  
  794.     /*
  795.      * Disable partitions of zero size
  796.      */
  797.     if (!pinfo->siz)    {
  798.         pinfo->flg &= ~P_EXISTS;
  799.     }
  800.  
  801.     /*
  802.      * Redraw the thing;
  803.      * if partition is disabled, shadow it and disable UP/DOWN buttons;
  804.      * otherwise setup the buttons, setup size string, and so on...
  805.      */
  806.     pno -= lowlim;
  807.     if (!(pinfo->flg & P_EXISTS)) {
  808.         pnl[objsizs[pno]].ob_spec = "Unused";
  809.         pnl[objsizs[pno]].ob_state = NORMAL;
  810.         pnl[objsizs[pno]].ob_flags = TOUCHEXIT;
  811.  
  812.         pnl[objups[pno]].ob_state = DISABLED;
  813.         pnl[objups[pno]].ob_flags = NONE;
  814.  
  815.         pnl[objdns[pno]].ob_state = DISABLED;
  816.         pnl[objdns[pno]].ob_flags = NONE;
  817.     } else {
  818.         stuffamt(pinfo->siz, sizstr[pno], 0);
  819.         pnl[objsizs[pno]].ob_spec = sizstr[pno];
  820.         pnl[objsizs[pno]].ob_state = NORMAL;
  821.         pnl[objsizs[pno]].ob_flags = TOUCHEXIT;
  822.  
  823.         pnl[objups[pno]].ob_state = NORMAL;
  824.         pnl[objups[pno]].ob_flags = TOUCHEXIT;
  825.  
  826.         pnl[objdns[pno]].ob_state = NORMAL;
  827.         pnl[objdns[pno]].ob_flags = TOUCHEXIT;
  828.     }
  829.  
  830.     /* set the partition numbers in the dialog box */
  831.     stpartnum(lowlim+pno+1, numstr[pno]);
  832.     (pnl[objnums[pno]].ob_spec)->te_ptext = numstr[pno];
  833.  
  834.     if (ok2draw) {
  835.         objc_draw(pnl, objsizs[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  836.         objc_draw(pnl, objups[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  837.         objc_draw(pnl, objdns[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  838.         objc_draw(pnl, objnums[pno], MAX_DEPTH, 0, 0, wdesk, hdesk);
  839.     }
  840.  
  841.  
  842. fixleft:
  843.  
  844.     /*
  845.      * Compute and redraw 'space left' indicator and
  846.      * calculat the total partitions number */
  847.  
  848.        sizleft = disksiz;
  849.     pinfo = headptr;
  850.     tolpart = 0;
  851.     while ((pinfo->flg & P_EXISTS) && (pinfo->siz > 0))     {
  852.             sizleft -= pinfo->siz;
  853.             tolpart++;  
  854.             pinfo = pinfo->next;
  855.     }
  856.     npart = tolpart;
  857.        stuffamt(sizleft, sizstr[4], 1);
  858.        (pnl[SEPLEFT].ob_spec)->te_ptext = sizstr[4];
  859.  
  860.     totalpart(tolpart, sizstr[5]);
  861.        (pnl[STOLPART].ob_spec)->te_ptext = sizstr[5];
  862.  
  863.     if (ok2draw)    {
  864.         objc_draw(pnl, SEPLEFT, MAX_DEPTH, 0, 0, wdesk, hdesk);
  865.         objc_draw(pnl, STOLPART, MAX_DEPTH, 0, 0, wdesk, hdesk);
  866.     }
  867. }
  868.  
  869. /*
  870.  * Atoi `amt', #blocks, into 999.9Mb (or something like that);
  871.  * assumes enough space in `str'.
  872.  */
  873. stuffamt(amt, str, flag)
  874. long amt;
  875. char *str;
  876. int flag;            /* 1: for Memory left box. */
  877. {
  878.     long mb, frac;
  879.     int i=0;
  880.  
  881.     mb = amt / 2048;
  882.     frac = amt - (2048 * mb);
  883.     if (frac / 16)
  884.         frac /= 205;        /* that's MEGABYTE / 10 */
  885.     else frac = 0;
  886.     if (frac < 0) frac = -frac;
  887.     if (mb < 0) mb = frac = 0;
  888.  
  889.     if (mb > 999)     {
  890.         *str++ = (mb / 1000) + '0';
  891.         i++;
  892.         mb -= 1000 * (mb / 1000);
  893.         if ((!mb) || (mb < 10))    { /* take care mb=1000 or 1001 case */
  894.             *str++ = '0';
  895.             *str++ = '0';
  896.             i += 2;
  897.         } else if (mb < 100)    { /* take care mb=1099 case */
  898.             *str++ = '0';
  899.             i++;
  900.         }
  901.     }
  902.     if (mb > 99) {
  903.         *str++ = (mb / 100) + '0';
  904.         i++;
  905.         mb -= 100 * (mb / 100);
  906.         if ((!mb) || (mb < 10))    {    /* take care mb=100 or 101 cases */
  907.             *str++ = '0';
  908.             i++;
  909.         }
  910.     }
  911.     if (mb > 9) {
  912.         *str++ = (mb / 10) + '0';
  913.         mb -= 10 * (mb / 10);
  914.         i++;
  915.     }
  916.     *str++ = mb + '0';
  917.     i++;
  918.  
  919.     if (frac) {
  920.         *str++ = '.';
  921.         *str++ = frac + '0';
  922.         i += 2;
  923.     }
  924.     *str++ = 'M';
  925.     *str++ = 'b';
  926.     i += 2;
  927.     if (flag)     {        /* for the Memory left box */
  928.         for (; i < 8; i++)
  929.             *str++ = ' ';
  930.     }
  931.     *str = '\0';
  932. }
  933.  
  934.  
  935. /*
  936.  * Partitin button number-to-object translation table.
  937.  */
  938.  
  939. int ppart[] = {
  940.     PPART0, PPART1, PPART2, PPART3,
  941.     PPART4, PPART5, PPART6, PPART7,
  942.     PPART8, PPART9, PPART10, PPART11,
  943.     PPART12, PPART13, PPART14
  944. };
  945.  
  946. /*
  947.  * Throw up menu of canned partitions;
  948.  *    Return PPOK on [OK],
  949.  *         PPCN on [CANCEL],
  950.  *         PPEDIT on [EDIT==>],
  951.  *         ERROR on some error.
  952.  *    if `flag' < 0, this is the first time 
  953.  *    putting up the menu.
  954.  */
  955.  
  956. spartmenu()
  957. {
  958.     int i, but, tem;
  959.     char *s, *pnam, pr_id[10];
  960.  
  961.     /* Figure out partition scheme id */
  962.     /*
  963.     figprid(disksiz, pr_id);
  964.     */
  965.     
  966.     if (menuflg < 0) {
  967.         menuflg = 1;
  968.        
  969.         setschm(disksiz, partnames);
  970.         /*
  971.         if (ttscsi)    {
  972.             setschm(disksiz, partnames);
  973.         } else     {
  974.             Get all available partition schemes from wincap 'ID' entries 
  975.             wallents(partnames, pr_id);
  976.         }
  977.         */
  978.     }
  979.  
  980.     for (i = 0, s = partnames; i < 15 && *s; ++i) {
  981.         p[ppart[i]].ob_type = G_BUTTON;
  982.     p[ppart[i]].ob_spec = (long)s;
  983.     p[ppart[i]].ob_state = NORMAL;
  984.     p[ppart[i]].ob_flags = SELECTABLE | RBUTTON;
  985.     while (*s++)
  986.         ;
  987.     }
  988.  
  989.     /* rest of buttons are invisible and untouchable */
  990.     for (; i < 15; ++i) {
  991.         p[ppart[i]].ob_type = G_IBOX;
  992.     p[ppart[i]].ob_spec = 0L;            /* no thickness */
  993.     p[ppart[i]].ob_state = DISABLED;        /* nobody home */
  994.     p[ppart[i]].ob_flags = NONE;            /* disabled */
  995.     }
  996.  
  997.     /* clean up rest of the form and throw it up */
  998.     p[PPOK].ob_state = NORMAL;
  999.     p[PPCN].ob_state = NORMAL;
  1000.     p[PPEDIT].ob_state = NORMAL;
  1001.     
  1002.     if((but = execform(p)) == PPCN || but == PPEDIT)
  1003.     return;
  1004.  
  1005.     /* search for partition they picked */
  1006.     pnlflg = 0;                /* partition scheme from menu */
  1007.     for (i = 0; i < 15; ++i)
  1008.     if (p[ppart[i]].ob_state & SELECTED)
  1009.         break;
  1010.     if (i >= 15) return but;        /* nothing changed */
  1011.     pnam = p[ppart[i]].ob_spec;
  1012.  
  1013.     /*
  1014.     if (!ttscsi)    {
  1015.         i = wgetent(pnam, pr_id);                ; (floppy access) 
  1016.         if (i != OK) {
  1017.             nopart[NOSCHPOK].ob_state = NORMAL;
  1018.                (nopart[NOSCHPR].ob_spec)->te_ptext = p[ppart[i]].ob_spec;
  1019.             execform(nopart);
  1020.             return ERROR;
  1021.         }
  1022.     }
  1023.     */
  1024.     npart = 4;
  1025.     ext = NO_EXT;        /* set no extended partition */
  1026.     if (headptr > 0)    free(headptr);
  1027.     if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)        {
  1028.         err(nomemory);
  1029.         if (pinfo > 0)    Mfree(pinfo);
  1030.         return ERROR;
  1031.     }
  1032.     inipart(&pinfo[0], npart);        /* initialized the 'pinfo' */
  1033.     npart = 0;
  1034.     msetpart(pinfo, pnam, disksiz);
  1035.     /*
  1036.     if (ttscsi)        {
  1037.         msetpart(pinfo, pnam, disksiz);
  1038.     } else {
  1039.         for (i = 0; i < 4; ++i)
  1040.             fillpart(i, &pinfo[i]);
  1041.     }
  1042.     */
  1043.     return but;
  1044. }
  1045.  
  1046.  
  1047. /* 
  1048.  * conver the partition number for the dialog box to the string .
  1049.  *
  1050.  */
  1051.  
  1052. stpartnum(num, str)
  1053.  
  1054. int num;
  1055. char *str;
  1056.  
  1057. {
  1058.     int  i = 0, j=0;
  1059.     char tem[20];
  1060.  
  1061.     /* set the partition number header */
  1062.     *str++ = '#';
  1063.     j++;
  1064.     /* conver the integer to ASCII */
  1065.     do    {    /* generate digits in reverse order */
  1066.         tem[i++] = num % 10 + '0';    /* get next digits */
  1067.     } while ((num /= 10) > 0);        /* delete it */
  1068.  
  1069.     for (; i > 0; )    { /* reverse string 'str' in place */
  1070.         *str++ = tem[--i];
  1071.         j++;
  1072.     }
  1073.     for (; j < 4; j++)
  1074.         *str++ = ' ';
  1075.     *str = '\0';
  1076.  
  1077. }
  1078.  
  1079.  
  1080.  
  1081. /*
  1082.  *  Place partition headers at the appropiate sectors.
  1083.  *    Input:
  1084.  *        pdev - physical device partitions belong to.
  1085.  *        part - partition structure containing the partitions'
  1086.  *               information.
  1087.  *    Return:
  1088.  *        OK - if everything is fine.
  1089.  *        ERROR - error occurs when testing header sectors.
  1090.  *    Comments:
  1091.  *        Making sure that the headers occupy consecutive good 
  1092.  *    sectors.  If necessary, sizes of partitions are adjusted to 
  1093.  *    achieve the above.
  1094.  *        If any size adjustment make a partition bigger than
  1095.  *    the maximum size, the partition will be adjusted to the maximum
  1096.  *    size leaving the excessive sectors wasted.
  1097.  */
  1098.  
  1099. spheader(pdev, part)
  1100.  
  1101. int pdev;    /* physical device number */
  1102. PART *part;    /* partition info */
  1103.  
  1104. {
  1105.     /* Maximum sizes for FAT, root directory and header <in sectors> */
  1106.     long  maxdent;        /* max num entries in root dir */
  1107.     long  start;        /* starting sector number of a partition */
  1108.     long  entries, nument();
  1109.     long  movehdr, temstart, moved, psiz;
  1110.     UWORD maxfsiz, maxdsiz, hdrsiz;
  1111.     long currbsiz;        /* size of BSL b4 pheader is executed */
  1112.     int  pno;            /* partition being dealt with */
  1113.     int  done;            /* tell if location of header is found */
  1114.     int  curr;            /* current sector of header being checked */
  1115.     int  ret;            /* return code from testing header sectors */
  1116.     int     spc;            /* sectors per cluster */
  1117.     int  kindfat;       /* 12 bits fat or 16 bits fat */
  1118.     int  step;            /* the index for check the partitions */
  1119.     long bigsect(), nsect;
  1120.     long stbigsect();
  1121.     long temsect, remain;
  1122.     long cell();
  1123.     
  1124.     
  1125.     /* get the BSL ready ofr later */
  1126.     entries = nument(MEDIA);
  1127.     sortbsl(entries);
  1128.     currbsiz = bslsiz;
  1129.  
  1130.     /* Determine actual sizes and starting sectors for all partitions */
  1131.     for (pno = 0; pno < npart; pno++) {
  1132.         
  1133.         /* Partition 0 starts right after root sect.  The rest starts right
  1134.            after its previous partition ???*/
  1135.         if (pno == 0)
  1136.             start = 1 + currbsiz; 
  1137.         else if (pno == 4)
  1138.             start = part[ext].p_st;    /* start in extened partition */
  1139.         else
  1140.             start = part[pno-1].p_st + part[pno-1].p_siz;
  1141.         
  1142.         /* Check if partition exists.  If it doesn't, move on to next one */
  1143.         if ((!(part[pno].p_flg & P_EXISTS)) || (pno == ext)) {
  1144.             part[pno].p_st = start;
  1145.             continue;
  1146.         }
  1147.         if (pno > 3)     {
  1148.             psiz = part[pno].p_siz - ROOTSECT;
  1149.         } else    {
  1150.             psiz = part[pno].p_siz;
  1151.         }
  1152.  
  1153.         /* estimate the bps */
  1154.         /* MAXSECT = 16MB - 8 */
  1155.         bps = cell((psiz-7)*BPS, (long)MAXSECT);
  1156.         /* the real pbs */
  1157.         bps = BPS * n2power((UWORD)cell(bps, (long)BPS));
  1158.         ratio = bps / BPS;
  1159.         nsect = psiz / ratio;
  1160.  
  1161.         /* Detail of calculations in part.c dopart() */
  1162.         /* find max FAT size. FAT16: 16 bits fat; FAT12: 12bits fat */
  1163.         maxfsiz = ((((nsect / SPC) + 2)*2) / bps) + 1;
  1164.         /* find max root dir entries */
  1165.         if (nsect < 0x5000L)    maxdent = NUMEN;
  1166.         else maxdent = nsect / 80;
  1167.         maxdent = (maxdent + (bps/BPDIR -1)) & ~(bps/BPDIR -1);
  1168.         /* find max root dir size */
  1169.         maxdsiz = (maxdent * BPDIR) / bps + 1;
  1170.  
  1171.            if (pno > 3)    {  /* they are extended partitions */
  1172.         /*-------------------------------------------------------*
  1173.          * Biggest possible header for a extended partition <in sectors> 
  1174.          *    =  Root sector + Boot Sector + 2 FATs + Root Dir    
  1175.          *-------------------------------------------------------*/
  1176.          /* convert it back to 512 bps size */
  1177.             hdrsiz = 1 + ratio + ((maxfsiz * 2) + maxdsiz) * ratio;
  1178.         } else
  1179.         /*-------------------------------------------------------*
  1180.          * Biggest possible header for a partition <in sectors>  *
  1181.          *    =  Boot Sector + 2 FATs + Root Dir         *
  1182.          *-------------------------------------------------------*/
  1183.          /* convert it back to 512 bps size */
  1184.             hdrsiz = (1 + (maxfsiz * 2) + maxdsiz) * ratio;
  1185.     
  1186.     /*-----------------------------------------------------------------*
  1187.      * Look for a chunk of sectors starting at "start" (or after, but  *
  1188.      * as close as possible) which is big enough to hold the biggest   *
  1189.      * possible header.                           *
  1190.      *-----------------------------------------------------------------*/
  1191.     done = 0;       /* assume correct location not found yet */
  1192.     moved = 0;
  1193.     while (!done) {
  1194.         /*----------------------------------------------------------*
  1195.          * Find out if header contains any bad sectors by checking    *
  1196.          * range of sectors to be occupied by the header against    *
  1197.          * the BSL.                                                    *
  1198.          *----------------------------------------------------------*/
  1199.         for (curr = 0; curr < hdrsiz; curr++)    {
  1200.             if (srchbsl(start+curr, entries) == YES)
  1201.                 break;
  1202.         }
  1203.         if (curr < hdrsiz)    {    /* bad sector found in header */
  1204.             /* move header to start after the bad sector */
  1205.             moved += curr + 1;
  1206.             start += curr + 1;
  1207.         } else {
  1208.                if ((ret = testhdr(pdev, start, hdrsiz)) < 0)
  1209.                  return ERROR;
  1210.             if (ret)    {    /* some bad sectors found in header */
  1211.                 entries = nument(MEDIA);
  1212.                 sortbsl(entries);
  1213.             } else {        /* all sectors belong ot header are good */
  1214.                 done = 1;
  1215.             }
  1216.         }
  1217.     }
  1218.     
  1219.     if (moved) {    /* header has been moved */
  1220.         /*-------------------------------------------------------*
  1221.          * Expand previous partition (except if the current one  *
  1222.          * is partition 0, then there is no previous partition), *
  1223.          * and enforce maximum partition size on it.         *
  1224.          *-------------------------------------------------------*/
  1225.         if (ratio > 1)    {    /* big sector */
  1226.             start -= moved;
  1227.             moved = stbigsect(moved);
  1228.             start += moved;
  1229.         }
  1230.         if (pno > 0) {
  1231.             if (part[pno-1].p_siz + moved > disksiz)
  1232.                 part[pno-1].p_siz = disksiz;
  1233.             else
  1234.                 part[pno-1].p_siz += moved;
  1235.         }
  1236.             
  1237.         /* Shrink size of current partition */
  1238.         part[pno].p_siz -= moved;
  1239.     } 
  1240.  
  1241.     /* Where current partition should start */
  1242.     part[pno].p_st = start;
  1243.  
  1244.     /* add the waist sectors of big partition to the next partition */
  1245.     /* partition #3 in the pinfo is the last partition */
  1246.     /* partition # npart-1 in the pinfo is the last partition in 
  1247.         the extended partition */
  1248.     if ((pno != 3) && (pno != npart - 1) && 
  1249.                     (part[pno].p_siz >= MB16))        { /* big partition */
  1250.         temsect = part[pno].p_siz;
  1251.         if (pno > 3)    { /* extended big partition */
  1252.            part[pno].p_siz = ROOTSECT + bigsect(part[pno].p_siz-ROOTSECT);
  1253.         } else {    /* prime big partition */
  1254.            part[pno].p_siz = bigsect(part[pno].p_siz);
  1255.         }
  1256.         remain = temsect - part[pno].p_siz;
  1257.         if (remain)    {
  1258.             part[pno+1].p_siz += remain;
  1259.             part[pno+1].p_st -= remain;
  1260.         }
  1261.     }
  1262.  
  1263.   }
  1264.     /* last existing partition has to sacrifice some space for the BSL    */
  1265.     /* and the root sector of device.                    */
  1266.     if ((ext == 3) || ((!(part[2].p_flg & P_EXISTS)) &&
  1267.                         (!(part[3].p_flg & P_EXISTS))))    { 
  1268.         /* the last partition is inside the extended partitions */
  1269.         step = npart;
  1270.         /* the total extended partition should not inculde the bad sector */
  1271.         /* list and root sector */
  1272.         part[ext].p_siz -= (currbsiz + 1);
  1273.     } else {    /* the last partition is in the prime partitions */
  1274.         step = NPARTS;
  1275.     }
  1276.     for (pno = step-1; pno >= 0; pno--) {
  1277.         if (part[pno].p_flg & P_EXISTS) {
  1278.             part[pno].p_siz -= (currbsiz + 1);
  1279.             break;
  1280.         }
  1281.     }
  1282.  
  1283.     /* have to move partitions (existing or not) which start
  1284.        right after the BSL if BSL has been expanded  */
  1285.     if (bslsiz > currbsiz) {        /* BSL becomes bigger? */
  1286.         for (pno = 0; pno < NPARTS; pno++) {
  1287.             if (part[pno].p_st == currbsiz + 1) {
  1288.                 part[pno].p_st = bslsiz + 1;
  1289.                 if (part[pno].p_siz > 0)
  1290.                     part[pno].p_siz -= (bslsiz - currbsiz);
  1291.             }
  1292.         }
  1293.     }
  1294.   return OK;    /* everything is fine */
  1295. }
  1296.  
  1297.  
  1298. long stbigsect(amt)
  1299. long amt;
  1300.  
  1301. {
  1302.     long numsect;
  1303.     if (ratio > 1)    {
  1304.         numsect = (amt % ratio) ? (amt / ratio + 1) : (amt /ratio);
  1305.         return(numsect * ratio);
  1306.     } else {
  1307.         return(amt);
  1308.     }
  1309. }
  1310.  
  1311.  
  1312. long bigsect(amt)
  1313. long amt;
  1314.  
  1315. {
  1316.     if (ratio > 1)    {
  1317.         return((amt / ratio) * ratio);
  1318.     } else {
  1319.         return(amt);
  1320.     }
  1321. }
  1322.  
  1323. /* 
  1324.  * Given size of a hard disk, figure out
  1325.  * the partition scheme ID to look for.
  1326.  * ID is 2 or more characters long.
  1327.  */
  1328. figprid(hdsiz, pr_id)
  1329. long hdsiz;
  1330. char pr_id[];
  1331. {
  1332.     UWORD mega, over;
  1333.     char numbuf[10];
  1334.     
  1335.     /* Round off disk size in megabytes */    
  1336.     mega = hdsiz / MEGABYTE;
  1337.     
  1338.     /* Round off disk size to nearest 10Mb */
  1339.     /*
  1340.     over = mega % 10;
  1341.     if (over >= 5)
  1342.        mega += (10 - over);
  1343.     else
  1344.        mega -= over;
  1345.     */
  1346.     itoa(mega, numbuf);
  1347.     strcpy(pr_id, numbuf);
  1348. }
  1349.  
  1350.  
  1351.  
  1352. /*
  1353.  * Check if partition scheme selected is _legal_.
  1354.  * _Legal_ means the scheme does not map to non-existing memory.
  1355.  * If it is not, prompt user to pick partition again.
  1356.  *    Input:
  1357.  *        pdev - physical unit we're trying to partition.
  1358.  *        xpinfo - partition block user selected.
  1359.  *    Return:
  1360.  *        OK - if partition scheme is _legal_.
  1361.  *        ERROR - if partition scheme is illegal.
  1362.  */
  1363.  
  1364. chkpart(pdev, xpinfo)
  1365. int pdev;
  1366. PART *xpinfo;
  1367. {
  1368.     char bs[512];
  1369.     SECTOR totsiz;
  1370.     int     i, ret;
  1371.     
  1372.     
  1373.     /* Get partition information from disk's root block.*/
  1374.     if ((ret = getroot(pdev, bs, (SECTOR)0)) != 0) {
  1375.         if (tsterr(ret) != OK)
  1376.             err(rootread);
  1377.         return (1);        /* return error but it is not a size too big */
  1378.     }
  1379.  
  1380.     disksiz = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  1381.     totsiz = 0;
  1382.     for (i = 0; i < NPARTS; i++) {
  1383.         if (xpinfo[i].p_flg & P_EXISTS)    {
  1384.             totsiz += xpinfo[i].p_siz;
  1385.         }
  1386.         if (totsiz > disksiz)
  1387.             return ERROR;     /* size too big */
  1388.     }
  1389.     return OK;
  1390. }
  1391.     
  1392.  
  1393.  
  1394. /*
  1395.  *  Make sure that sectors assigned to a partition header are GOOD.
  1396.  *    Input:
  1397.  *        pdev - physical device number partition belongs to.
  1398.  *        start - starting (physical) sector number header starts.
  1399.  *        hdrsiz - number of sectors header occupies.
  1400.  *    Return:
  1401.  *        OK - if all sectors in header are good.
  1402.  *        positive number - if entries are added to BSL in testing
  1403.  *                    the header.
  1404.  *        ERROR - if somewhere the process went wrong.
  1405.  *    Comments:
  1406.  *        Bad Sectors found are added as USER bad sectors.  
  1407.  *    First, because we can't expand the VENDOR list while preserving
  1408.  *    the USER list.  Second, this is ok, because even if the USER list
  1409.  *    is full, the user should reformat the disk anyway, and if the
  1410.  *    sector is REALLY bad, it would be discovered again then.
  1411.  */
  1412. testhdr(pdev, start, hdrsiz)
  1413. int pdev;
  1414. SECTOR start;
  1415. UWORD hdrsiz;
  1416. {
  1417.     long size, pattern;
  1418.     extern long longrandom();
  1419.     extern int tformat;        /* flag */
  1420.     UWORD sectcnt, list;
  1421.     int ret, nbad, clean=1;
  1422.     SECTOR sect;
  1423.     char *buf;        /* buffer with test data */
  1424.     
  1425.     size = (long)hdrsiz << 9;
  1426.     if ((buf = (char *)Malloc(size)) <= 0) {
  1427.         err(nomemory);
  1428.         ret = NOMEM;
  1429.         goto wrapup;
  1430.     }
  1431.         
  1432.     /*
  1433.      * Try to write to header's sectors.
  1434.      */
  1435.     pattern = longrandom();
  1436.     fillbuf(buf, size, pattern);
  1437.     sectcnt = hdrsiz;
  1438.     sect = start;
  1439.     nbad = 0;
  1440.  
  1441.     if ((ret = wrsects(pdev, sectcnt, buf, sect)) != 0) {
  1442.         if (tsterr(ret) == OK) {
  1443.             ret = ERROR;
  1444.             goto wrapup;
  1445.         }
  1446.         clean = 0;
  1447.         
  1448.         while (sectcnt) {    /* find out which sector is indeed bad */
  1449.         if ((ret = wrsects(pdev, 1, 0L, sect)) != 0) {
  1450.             if (tsterr(ret) == OK) {
  1451.                 ret = ERROR;
  1452.                 goto wrapup;
  1453.             }
  1454.             if (sect < 3) {
  1455.                 ret = err(rsrvbad);
  1456.                 goto wrapup;
  1457.             }
  1458.                     
  1459.                  badbuf[nbad++] = sect;    /* store bad sector num */
  1460.                     
  1461.                 /* buffer is filled up, have to add bad sectors
  1462.                    found so far to the BSL before continuing.   */
  1463.                 if (nbad == WARNBADSECTS) {
  1464.                     /* Decide which list to add to */
  1465.                     if (tformat == TRUE)
  1466.                         list = VENDOR;
  1467.                     else list = USER;
  1468.                        if ((ret=addbsl(pdev, list, nbad)) < 0) {
  1469.                            ret = err(rsrvbad);
  1470.                            goto wrapup;
  1471.                        }
  1472.                        nbad = 0;    /* start counting again */
  1473.                 }
  1474.             }
  1475.             sect++;
  1476.             sectcnt--;
  1477.         }
  1478.         if (nbad) {    /* there are bad sectors found not added to BSL yet */
  1479.             /* Decide which list to add to */
  1480.             if (tformat == TRUE)
  1481.                 list = VENDOR;
  1482.             else list = USER;
  1483.             if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1484.                 ret = ERROR;
  1485.                 goto wrapup; 
  1486.             }
  1487.             nbad = 0;
  1488.         }
  1489.     }
  1490.     
  1491.     /* Try to read header's sectors */
  1492.     sectcnt = hdrsiz;
  1493.     sect = start;
  1494.     nbad = 0;
  1495.     if ((ret = rdsects(pdev, sectcnt, buf, sect)) != 0) {
  1496.         if (tsterr(ret) == OK) {
  1497.             ret = ERROR;
  1498.             goto wrapup;
  1499.         }
  1500.         clean = 0;
  1501.         
  1502.         while (sectcnt) {    /* find out which sector is indeed bad */
  1503.         if ((ret = rdsects(pdev, 1, buf, sect)) != 0) {
  1504.             if (tsterr(ret) == OK) {
  1505.                 ret = ERROR;
  1506.                 goto wrapup;
  1507.             }
  1508.                 if (sect < 3) {
  1509.             ret = err(rsrvbad);
  1510.             goto wrapup;
  1511.         }
  1512.                     
  1513.                  badbuf[nbad++] = sect;    /* store bad sector num */
  1514.                     
  1515.                 /* buffer is filled up, have to add bad sectors
  1516.                    found so far to the BSL before continuing.   */
  1517.                 if (nbad == WARNBADSECTS) {
  1518.                     /* Decide which list to add to */
  1519.                     if (tformat == TRUE)
  1520.                     list = VENDOR;
  1521.                     else list = USER;
  1522.                        if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1523.                            ret = ERROR;
  1524.                            goto wrapup;
  1525.                        }
  1526.                        nbad = 0;    /* start counting again */
  1527.                 }
  1528.             }
  1529.             sect++;
  1530.             sectcnt--;
  1531.         }
  1532.         if (nbad) {    /* there are bad sectors found not added to BSL yet */
  1533.             /* Decide which list to add to */
  1534.             if (tformat == TRUE)
  1535.                 list = VENDOR;
  1536.             else list = USER;
  1537.             if ((ret = addbsl(pdev, list, nbad)) < 0) {
  1538.                 ret = ERROR;
  1539.                 goto wrapup; 
  1540.             }
  1541.             nbad = 0;
  1542.         }
  1543.     }
  1544. wrapup:
  1545.     if (buf > 0)  Mfree((long)buf);
  1546.     
  1547.     if (ret < 0)
  1548.         return ret;
  1549.         
  1550.     if (!clean) {
  1551.         /* write new bsl back to disk */
  1552.         if (wrbsl(pdev) != OK) {
  1553.             return ERROR;
  1554.         }
  1555.         return 1;
  1556.     }
  1557.         
  1558.     return OK;
  1559. }
  1560.  
  1561. long
  1562. cell(top, bottom)
  1563. long top;
  1564. long bottom;
  1565. {
  1566.     return ((top % bottom) ? (top / bottom + 1) :
  1567.             (top / bottom));
  1568. }
  1569.  
  1570.  
  1571. n2power(num)
  1572. UWORD num;
  1573. {
  1574.     UWORD power = 1;
  1575.  
  1576.     for (;;)    {
  1577.         if (num <= power )    {
  1578.             return (power);
  1579.         }
  1580.         power <<= 1;
  1581.     } 
  1582. }
  1583.  
  1584.  
  1585. DPART
  1586. *addr(index)
  1587. int index;
  1588. {
  1589.     DPART *temptr;
  1590.     int i;
  1591.  
  1592.     if (index < 0)    return nill;
  1593.     if (!index) return (headptr);
  1594.     temptr = headptr->next;
  1595.     for (i = 1; i < index; i++)    {
  1596.         temptr = temptr->next;
  1597.     }
  1598.     return (temptr);
  1599. }
  1600.  
  1601. DPART
  1602. *last()
  1603. {
  1604.     DPART *temptr;
  1605.     int i;
  1606.  
  1607.     if (!headptr) return (headptr);
  1608.     temptr = headptr;
  1609.     while (temptr->next)
  1610.         temptr = temptr->next;
  1611.     return (temptr);
  1612. }
  1613.  
  1614.  
  1615.  
  1616. creatmem(num)
  1617. int num;        /* number of block to malloc */
  1618. {
  1619.     DPART *temptr;
  1620.     DPART *last();
  1621.     int i;
  1622.  
  1623.     if (headptr == nill)    {
  1624.         if ((headptr = (DPART *)mymalloc((int)sizeof(DPART))) <= 0)    {;
  1625.             err(nomemory);
  1626.             if (headptr > 0) free(headptr);
  1627.             return ERROR;
  1628.         }
  1629.         headptr->next = nill;
  1630.         headptr->siz = 0L;
  1631.         headptr->flg = 0;
  1632.     }
  1633.     temptr = last();
  1634.     for (i = 0; i < num; i++)    {
  1635.         if ((temptr->next = (DPART *)mymalloc((int)sizeof(DPART))) <= 0)    {
  1636.             err(nomemory);
  1637.             if (headptr > 0) free(headptr);
  1638.             return ERROR;
  1639.  
  1640.         }
  1641.         temptr = temptr->next;
  1642.         temptr->next = nill;
  1643.         temptr->siz = 0L;
  1644.         temptr->flg = 0;
  1645.     }
  1646. }
  1647.  
  1648.  
  1649. dpart2part(extpart)
  1650. int extpart ;    /* set the extended pointer in the 4th place */
  1651. {
  1652.     int i;
  1653.     DPART *temptr;
  1654.  
  1655.     /* if npart > 4; need 1 more space for the extended partition */
  1656.     if (npart > 4)    {
  1657.         i = npart - extend;    /* the index that extended form the end of part. */
  1658.         npart += NPARTS-extpart;    /* add 1 extra space for the extended */
  1659.                                     /* partition and 0 or 1 or 2 space for */
  1660.                                     /* the prime partition in the root */
  1661.         extend = npart - i;    /* move 2 space for 2 prime partition in the root */
  1662.     } else {                /* set the extpart to -1 */
  1663.         npart = 4;
  1664.         extpart = -1;
  1665.         ext = NO_EXT;
  1666.     }
  1667.     if ((pinfo = (PART *)Malloc((long)sizeof(PART)*npart)) <= 0)    {
  1668.         err(nomemory);
  1669.         if (pinfo > 0) Mfree(pinfo);
  1670.         free(headptr);
  1671.         return ERROR;
  1672.     }
  1673.     inipart(pinfo, npart);  
  1674.     temptr = headptr;
  1675.     for (i = 0; i < npart; i++)        {
  1676.         if (!(temptr->flg & P_EXISTS)) {
  1677.             if (sizleft > 0) {
  1678.                 if (temptr->siz > sizleft) {
  1679.                     pinfo[i].p_siz = sizleft;
  1680.                 }
  1681.                 sizleft -= temptr->siz;
  1682.             }
  1683.         } else {
  1684.             pinfo[i].p_siz = temptr->siz;
  1685.             pinfo[i].p_flg = P_EXISTS;
  1686.             if (i == extpart)    {
  1687.                 pinfo[i].p_id[0] = 'X';
  1688.                 pinfo[i].p_id[1] = 'G';
  1689.                 pinfo[i].p_id[2] = 'M';
  1690.                 pinfo[i].p_siz = 0L;
  1691.             } else if ((extpart == 1) && ((i == 2) || (i==3)))    {
  1692.                 pinfo[i].p_flg = 0;
  1693.                 pinfo[i].p_siz = 0L;
  1694.             } else if ((extpart == 2) && (i==3))    {
  1695.                 pinfo[i].p_flg = 0;
  1696.                 pinfo[i].p_siz = 0L;
  1697.             } else if (temptr->siz < MB16)    {
  1698.                 pinfo[i].p_id[0] = 'G';
  1699.                 pinfo[i].p_id[1] = 'E';
  1700.                 pinfo[i].p_id[2] = 'M';
  1701.                 temptr = temptr->next;
  1702.             } else {
  1703.                 pinfo[i].p_id[0] = 'B';
  1704.                 pinfo[i].p_id[1] = 'G';
  1705.                 pinfo[i].p_id[2] = 'M';
  1706.                 temptr = temptr->next;
  1707.             }
  1708.         }
  1709.     }
  1710.     free(headptr);
  1711.     if (extpart != NO_EXT)    {
  1712.         asmpart(extpart);
  1713.     }
  1714.     return OK;
  1715. }
  1716.  
  1717.  
  1718. asmpart(extpart)
  1719. int extpart ;    /* the extended partition pointer */
  1720. {
  1721.     int i;
  1722.  
  1723.     /* # of extened partition to add up */
  1724.     for (i = 4; i < extend; i++)        {
  1725.         pinfo[extpart].p_siz += pinfo[i].p_siz;
  1726.     }
  1727.     if (extpart == 3)    {
  1728.         return OK;        /* done */
  1729.     } else     {
  1730.         /* put the last (npart-extend-1) partitions to */
  1731.         /* the 3rd or 4th place as prime partitions */
  1732.         i = extend;
  1733.         if (i < npart)    {
  1734.             pinfo[extpart+1].p_siz = pinfo[i].p_siz;
  1735.             pinfo[extpart+1].p_flg = P_EXISTS;
  1736.             if (pinfo[extpart+1].p_siz < MB16)    {
  1737.                 pinfo[extpart+1].p_id[0] = 'G';
  1738.                 pinfo[extpart+1].p_id[1] = 'E';
  1739.                 pinfo[extpart+1].p_id[2] = 'M';
  1740.             } else {
  1741.                 pinfo[extpart+1].p_id[0] = 'B';
  1742.                 pinfo[extpart+1].p_id[1] = 'G';
  1743.                 pinfo[extpart+1].p_id[2] = 'M';
  1744.             }
  1745.             pinfo[i].p_flg = 0;
  1746.             pinfo[i].p_siz = 0L;
  1747.             pinfo[i].p_id[0] = '0';
  1748.             pinfo[i].p_id[1] = '0';
  1749.             pinfo[i].p_id[2] = '0';
  1750.             npart--;
  1751.         } 
  1752.         if (i++ < npart)    {
  1753.             pinfo[extpart+2].p_siz = pinfo[i].p_siz;
  1754.             pinfo[extpart+2].p_flg = P_EXISTS;
  1755.             if (pinfo[extpart+2].p_siz < MB16)    {
  1756.                 pinfo[extpart+2].p_id[0] = 'G';
  1757.                 pinfo[extpart+2].p_id[1] = 'E';
  1758.                 pinfo[extpart+2].p_id[2] = 'M';
  1759.             } else {
  1760.                 pinfo[extpart+2].p_id[0] = 'B';
  1761.                 pinfo[extpart+2].p_id[1] = 'G';
  1762.                 pinfo[extpart+2].p_id[2] = 'M';
  1763.             }
  1764.             pinfo[i].p_flg = 0;
  1765.             pinfo[i].p_siz = 0L;
  1766.             pinfo[i].p_id[0] = '0';
  1767.             pinfo[i].p_id[1] = '0';
  1768.             pinfo[i].p_id[2] = '0';
  1769.             npart--;
  1770.         }
  1771.     }
  1772. }
  1773.  
  1774.  
  1775. part2dpart(numpart)
  1776. int numpart;
  1777. {
  1778.  
  1779.     int i;
  1780.     DPART *temptr;
  1781.  
  1782.     headptr = nill;
  1783.     if (creatmem(numpart) == ERROR) {
  1784.         return ERROR;
  1785.     }
  1786.     temptr = headptr;
  1787.     for (i = 0; i < numpart; i++) {
  1788.         if (pinfo[i].p_flg & P_EXISTS)    {
  1789.             temptr->siz = pinfo[i].p_siz;
  1790.             temptr->flg = P_EXISTS;
  1791.         } 
  1792.         temptr = temptr->next;
  1793.     }
  1794. }
  1795.